package com.pureut.production.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pureut.common.core.exception.GlobalException;
import com.pureut.common.core.web.domain.AjaxResult;
import com.pureut.common.datascope.annotation.DataScope;
import com.pureut.common.security.utils.DictUtils;
import com.pureut.common.security.utils.SecurityUtils;
import com.pureut.production.domain.DegreasDocument;
import com.pureut.production.domain.DegreasOutput;
import com.pureut.production.domain.DegreasOutputDetail;
import com.pureut.production.domain.MaterialFinished;
import com.pureut.production.domain.dto.*;
import com.pureut.production.domain.vo.*;
import com.pureut.production.mapper.DegreasDocumentMapper;
import com.pureut.production.mapper.DegreasOutputDetailMapper;
import com.pureut.production.mapper.DegreasOutputMapper;
import com.pureut.production.mapper.MaterialFinishedMapper;
import com.pureut.production.service.DegreasDocumentService;
import com.pureut.production.service.DegreasOutputService;
import com.pureut.production.service.SpunlaceOrderService;
import com.pureut.system.api.FeignService;
import com.pureut.system.api.QualityFeginService;
import com.pureut.system.api.SchedulingPlanFeignService;
import com.pureut.system.api.StorageFegin;
import com.pureut.system.api.domain.StockOutInfoDetail;
import com.pureut.system.api.domain.SysDictData;
import com.pureut.system.api.vo.DegreasByUpdateVo;
import com.pureut.system.api.vo.FeginProductionPickingVo;
import com.pureut.system.api.vo.QualitySchemeConfigurationVo;
import com.pureut.system.api.vo.SchedulingTake;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 脱脂制令单实现层
 */
@Service
public class DegreasDocumentServiceImpl extends ServiceImpl<DegreasDocumentMapper, DegreasDocument> implements DegreasDocumentService {
    /**
     * 脱脂制令单mapper
     */
    @Resource
    DegreasDocumentMapper degreasDocumentMapper;

    /**
     * 基础模块fegin
     */
    @Resource
    FeignService feignService;

    /**
     * 仓库模块fegin
     */
    @Resource
    StorageFegin storageFegin;

    /**
     * 公共无聊mapper
     */
    @Resource
    MaterialFinishedMapper materialFinishedMapper;

    /**
     * 品质检验fegin
     */
    @Resource
    QualityFeginService qualityFeginService;

    /**
     * 排程fegin
     */
    @Resource
    SchedulingPlanFeignService schedulingPlanFeignService;

    /**
     * 脱脂产出service
     */
    @Lazy
    @Resource
    DegreasOutputService degreasOutputService;

    /**
     * 脱脂产出明细mapper
     */
    @Resource
    DegreasOutputDetailMapper degreasOutputDetailMapper;

    /**
     * 脱脂产出mapper
     */
    @Resource
    DegreasOutputMapper degreasOutputMapper;

    /**
     * 水刺制令单mapper
     */
    @Lazy
    @Resource
    SpunlaceOrderService spunlaceOrderService;

    /**
     * 排程fegin
     */
    @Resource
    SchedulingPlanFeignService SchedulingPlanFeignService;

    /**
     * 脱脂制令单列表
     *
     * @param degreasDocumentVo
     * @return
     */
    @Override
    @DataScope(deptAlias = "a")
    public List<DegreasDocumentDto> getList(DegreasDocumentVo degreasDocumentVo) {

        List<DegreasDocumentDto> degreasDocumentList = degreasDocumentMapper.getDegreasDocumentList(degreasDocumentVo);
        //单位
        List<SysDictData> unitArray = DictUtils.getDictCache("sys_material_unit");
        Map<String, String> unitMap = unitArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        for (DegreasDocumentDto entity : degreasDocumentList) {
            //单位
            entity.setMaterialUnitDict(unitMap.get(entity.getMaterialUnit()));
        }
        return degreasDocumentList;
    }

    /**
     * 新增
     *
     * @param degreasDocumentVo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addDegreas(DegreasDocumentVo degreasDocumentVo) throws Exception {

        DegreasDocument degreasDocument = new DegreasDocument();
        //上线时校验此物料/物料类别是否在质量管理中配置了检验方案，未配置则提示“此物料未配置检验方案，无法手动上线”，配置了则上线成功
        MaterialFinished materialFinished = materialFinishedMapper.selectOne(new QueryWrapper<MaterialFinished>().lambda().eq(MaterialFinished::getMaterialCode, degreasDocumentVo.getMaterialCode()));
        QualitySchemeConfigurationVo qualitySchemeConfigurationVo = new QualitySchemeConfigurationVo();
        qualitySchemeConfigurationVo.setItemRank(2);
        qualitySchemeConfigurationVo.setCategory(Integer.parseInt(materialFinished.getCategory()));
        qualitySchemeConfigurationVo.setMaterialCategory(materialFinished.getMaterialType());
        qualitySchemeConfigurationVo.setMaterialCode(degreasDocumentVo.getMaterialCode());
        boolean check = qualityFeginService.check(qualitySchemeConfigurationVo);

        //获取车间信息
        String lineCode = degreasDocumentVo.getLineCode();
        String workshopCode = feignService.getWorkshopCode(lineCode);
        String authorityCoding = feignService.getAuthorityCoding("productionTube:produAdm:degrproduc:degnproduc:list");
        degreasDocument.setDegreasOrderNumber(authorityCoding)
                .setMaterialCode(degreasDocumentVo.getMaterialCode())
                .setWorkshopCode(workshopCode)
                .setLevelProduction(1)
                .setStatus(1)
                .setLineCode(degreasDocumentVo.getLineCode())
                .setPlanWeight(degreasDocumentVo.getPlanWeight())
                .setEstimatedTime(degreasDocumentVo.getEstimatedTime())
                .setRemark(degreasDocumentVo.getRemark())
                .setDegreasMark(degreasDocumentVo.getDegreasMark())
                .setCreateTime(new Date())
                .setCreateBy(SecurityUtils.getUsername())
                .setDeptId(SecurityUtils.getDeptId())
                .setBomNumber(degreasDocumentVo.getBomNumber());
        if (check) {
            degreasDocument.setQualityStandard(1);
        } else {
            degreasDocument.setQualityStandard(2);
        }
        boolean b = save(degreasDocument);
        if (b) {
            //生成生产领料单
            FeginProductionPickingVo feginProductionPickingVo = new FeginProductionPickingVo();
            feginProductionPickingVo.setMaterialCode(degreasDocument.getMaterialCode())
                    .setProductionLine(degreasDocument.getLineCode())
                    .setMoNumber(degreasDocument.getDegreasOrderNumber())
                    .setPlannedWeight(degreasDocument.getPlanWeight())
                    .setList(degreasDocumentVo.getList());
            storageFegin.addAutoProductionByDegreas(feginProductionPickingVo);
        }
        return b;
    }

    /**
     * 脱脂制令单修改
     *
     * @param degreasDocumentVo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateDegreas(DegreasDocumentVo degreasDocumentVo) {
        DegreasDocument degreasDocument = getById(degreasDocumentVo.getId());
        //只能修改状态为“待上线”的单据
        if (degreasDocument.getStatus() == 1) {
            String degreasOrderNumber = degreasDocument.getDegreasOrderNumber();
            double planWeight = degreasDocumentVo.getPlanWeight();
            List<StockOutInfoDetail> list = degreasDocumentVo.getList();
            //获取车间信息
            String lineCode = degreasDocumentVo.getLineCode();
            String workshopCode = feignService.getWorkshopCode(lineCode);
            //修改当前脱脂制令单
            degreasDocument.setMaterialCode(degreasDocumentVo.getMaterialCode())
                    .setLineCode(degreasDocumentVo.getLineCode())
                    .setWorkshopCode(workshopCode)
                    .setPlanWeight(degreasDocumentVo.getPlanWeight())
                    .setEstimatedTime(degreasDocumentVo.getEstimatedTime())
                    .setRemark(degreasDocumentVo.getRemark())
                    .setBomNumber(degreasDocumentVo.getBomNumber())
                    .setDegreasMark(degreasDocumentVo.getDegreasMark());
            boolean b = updateById(degreasDocument);
            if (b) {
                DegreasByUpdateVo degreasByUpdateVo = new DegreasByUpdateVo();
                AjaxResult modelingLineInfo = feignService.getModelingLineInfo(lineCode);
                SysLineDto data = JSON.parseObject(JSON.toJSONString(modelingLineInfo.get("data")), SysLineDto.class);

                degreasByUpdateVo.setLineCode(lineCode)
                        .setDegreasOrderNumber(degreasOrderNumber)
                        .setPlanWeight(planWeight)
                        .setProductionLineName(data.getLineName())
                        .setList(list);
                storageFegin.updateByDegreas(degreasByUpdateVo);
            }
            return b;
        } else {
            throw new GlobalException("只能修改状态为“待上线”的单据");
        }
    }

    /**
     * 上线
     *
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean onLine(Long id) {
        DegreasDocument degreasDocument = getById(id);
        if (degreasDocument.getStatus() == 1 || degreasDocument.getStatus() == 3) {
            //若上线制令单关联的线别下有其他“生产中”的制令单，提示“当前线别存在正在生产的脱脂制令单，无法手动上线”
            List<DegreasDocument> degreasDocuments = degreasDocumentMapper.selectList(new QueryWrapper<DegreasDocument>().lambda().eq(DegreasDocument::getLineCode, degreasDocument.getLineCode()).eq(DegreasDocument::getStatus, 2));
            if (degreasDocuments.size() > 0) {
                throw new GlobalException("当前线别存在正在生产的脱脂制令单，无法手动上线");
            }
            //对暂停后再次上线的单据不再生成脱脂产出的数据
            if (degreasDocument.getStatus() == 3) {
                DegreasOutput degreasOutput = degreasOutputMapper.selectOne(new QueryWrapper<DegreasOutput>().lambda().eq(DegreasOutput::getDegreasOrderNumber, degreasDocument.getDegreasOrderNumber()));
                if (degreasOutput != null) {
                    degreasOutput.setProductStatus(2);
                    //同时修改脱脂制令单数据状态为生产中
                    degreasDocument.setStatus(2);
                    degreasOutputService.updateById(degreasOutput);
                    return updateById(degreasDocument);
                }
            }
            //上线时校验此物料/物料类别是否在质量管理中配置了检验方案，未配置则提示“此物料未配置检验方案，无法手动上线”，配置了则上线成功
            MaterialFinished materialFinished = materialFinishedMapper.selectOne(new QueryWrapper<MaterialFinished>().lambda().eq(MaterialFinished::getMaterialCode, degreasDocument.getMaterialCode()));
            QualitySchemeConfigurationVo qualitySchemeConfigurationVo = new QualitySchemeConfigurationVo();
            qualitySchemeConfigurationVo.setItemRank(2);
            qualitySchemeConfigurationVo.setCategory(Integer.parseInt(materialFinished.getCategory()));
            qualitySchemeConfigurationVo.setMaterialCategory(materialFinished.getMaterialType());
            qualitySchemeConfigurationVo.setMaterialCode(degreasDocument.getMaterialCode());
            boolean check = qualityFeginService.check(qualitySchemeConfigurationVo);
            if (check) {
                degreasDocument.setQualityStandard(1);
            } else {
                throw new GlobalException("此物料未配置检验方案，无法手动上线");
            }
            //生成脱脂产出数据
            DegreasOutputVo degreasOutputVo = new DegreasOutputVo();
            degreasOutputVo.setDegreasOrderNumber(degreasDocument.getDegreasOrderNumber());
            degreasOutputVo.setLineCode(degreasDocument.getLineCode());
            degreasOutputVo.setPlanWeight(degreasDocument.getPlanWeight());
            degreasOutputVo.setMaterialCode(degreasDocument.getMaterialCode());
            boolean b = degreasOutputService.addDegreasOutput(degreasOutputVo);
            if (b) {
                //上线后，单据状态更新为“生产中”
                degreasDocument.setStatus(2);
                return updateById(degreasDocument);
            } else {
                throw new GlobalException("生成脱脂产出数据失败");
            }
        } else {
            throw new GlobalException("只能对状态为“待上线、暂停”的单据进行上线操作");
        }
    }

    /**
     * 停产
     *
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean stop(Long id) {
        DegreasDocument degreasDocument = getById(id);
        if (degreasDocument.getStatus() == 2) {
            degreasDocument.setStatus(3);
            //同步修改对应脱脂产出数据
            DegreasOutput degreasOutput = degreasOutputMapper.selectOne(new QueryWrapper<DegreasOutput>().lambda().eq(DegreasOutput::getDegreasOrderNumber, degreasDocument.getDegreasOrderNumber()));
            degreasOutput.setProductStatus(1);
            boolean b = degreasOutputService.updateById(degreasOutput);
            if (b) {
                updateById(degreasDocument);
            }
            return b;
        } else {
            throw new GlobalException("只能对状态为“生产中”的单据进行停产操作");
        }
    }

    /**
     * 关结
     *
     * @param closeVo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean close(CloseVo closeVo) {
        DegreasDocument degreasDocument = getById(closeVo.getId());
        //只能对状态为“待上线、暂停”状态的单据进行关结
        if (degreasDocument.getStatus() == 1 || degreasDocument.getStatus() == 3) {
            //若关结的制令单存在“待入库”的物料（脱脂产出页面的下表中），则进行提示“该脱脂制令单还有物料未入库，不可关结”
            DegreasOutput degreasOutput = degreasOutputMapper.selectOne(new QueryWrapper<DegreasOutput>().lambda().eq(DegreasOutput::getDegreasOrderNumber, degreasDocument.getDegreasOrderNumber()));
            degreasOutput.setProductStatus(4);
            //获取该脱脂产出下的明细数据
            List<DegreasOutputDetail> degreasOutputDetails = degreasOutputDetailMapper.selectList(new QueryWrapper<DegreasOutputDetail>().lambda().eq(DegreasOutputDetail::getDegreasOrderNumber, degreasOutput.getDegreasOrderNumber()));
            boolean isAll = true;
            for (DegreasOutputDetail entity : degreasOutputDetails) {
                if (entity.getStatus() == 1) {
                    isAll = false;
                    break;
                }
            }
            if (isAll) {
                degreasOutputService.updateById(degreasOutput);
                //关结后，单据状态更新为“已关结”，作为最终状态
                degreasDocument.setStatus(5);
                degreasDocument.setCloseReason(closeVo.getCloseReason());
                degreasDocument.setCloseBy(SecurityUtils.getUsername());
                degreasDocument.setCloseTime(new Date());
                return updateById(degreasDocument);
            } else {
                throw new GlobalException("该脱脂制令单还有物料未入库，不可关结");
            }
        } else {
            throw new GlobalException("只能对状态为“待上线、暂停”状态的单据进行关结");
        }
    }

    /**
     * 删除
     *
     * @param id
     * @return
     */
    @Override
    public boolean deleteDegreasDocument(Long id) {
        DegreasDocument degreasDocument = getById(id);
        //只能删除状态为“待上线”的单据，若选择删除其他状态的单据，则提示“只能删除“待上线”状态的单据”
        if (degreasDocument.getStatus() == 1) {
            //删除后，对应的生产领料单若为“待确认”，则删除生产领料单，若为“待出库”，则关结，若已出库，则由生产人员手动处理
            String degreasOrderNumber = degreasDocument.getDegreasOrderNumber();
            storageFegin.deleteByDegreas(degreasOrderNumber);
            return removeById(degreasDocument);
        } else {
            throw new GlobalException("只能删除“待上线”状态的单据");
        }
    }

    /**
     * 查看
     *
     * @param id
     * @return
     */
    @Override
    public DegreasDocumentDto queryDegreasDocument(Long id) {

        DegreasDocumentDto documentDto = degreasDocumentMapper.getDataById(id);
        //获取线别id
        String lineCode = documentDto.getLineCode();
        Long lineId = feignService.getLineId(lineCode);
        //计算计划工时
        String materialCode = documentDto.getMaterialCode();
        AjaxResult ajaxResult = schedulingPlanFeignService.hoursOnById(lineId, materialCode);
        if (ajaxResult == null) {
            throw new GlobalException("该线别上有没有标准工时");
        }
        SchedulingHoursDto data = JSON.parseObject(JSON.toJSONString(ajaxResult.get("data")), SchedulingHoursDto.class);

        //标准工时（转化为秒）
        int workingHours = data.getWorkingHours();
        //单位
        int hoursUnit = data.getHoursUnit();
        //单位为KG/S
        if (hoursUnit == 2) {
            //计划重量/标准工时/360
            BigDecimal bigDecimalPlanWeight = new BigDecimal(String.valueOf(documentDto.getPlanWeight()));
            BigDecimal bigDecimalWorkingHours = new BigDecimal(String.valueOf(workingHours));
            BigDecimal divide = bigDecimalWorkingHours.divide(new BigDecimal("60"), RoundingMode.UP);
            BigDecimal divide1 = bigDecimalPlanWeight.divide(divide, RoundingMode.UP);
            BigDecimal divideResult = divide1.divide(new BigDecimal("60"), RoundingMode.UP);
            //预计工时
            documentDto.setResultTime(divideResult.toString());
            //预计完工时间
            SchedulingTake schedulingTake = new SchedulingTake();
            schedulingTake.setLineId(lineId);
            long expStartTime = documentDto.getEstimatedTime().getTime();
            double expWhen = Double.parseDouble(divideResult.toString());
            Date date = schedulingPlanFeignService.finishTime(lineId, expStartTime, expWhen);
            documentDto.setFinishWorkTime(date);

        } else {
            throw new GlobalException("该物料对应的排程计划工时单位不匹配");
        }
        //BOM查询出来的物料列表
        String bomNumber = documentDto.getBomNumber();
        AjaxResult halfBomDetailData = feignService.getHalfBomDetailData(bomNumber);
        List<BomDetailListDto> bomDetailList = JSON.parseArray(JSON.toJSONString(halfBomDetailData.get("data")), BomDetailListDto.class);
        if (bomDetailList==null) {
            throw new GlobalException("为获取到相关bom数据，请核实");
        }

        List<BomDetailDto> bomDetailDtoList = new ArrayList<>();
        for (BomDetailListDto entity : bomDetailList) {
            BomDetailDto bomDetailDto = new BomDetailDto();
            MaterialFinished materialFinished = materialFinishedMapper.selectOne(new QueryWrapper<MaterialFinished>().lambda().eq(MaterialFinished::getMaterialCode, entity.getMaterialCode()));
            bomDetailDto.setMaterialName(materialFinished.getMaterialName());
            bomDetailDto.setMaterialCode(materialFinished.getMaterialCode());
            bomDetailDto.setMaterialSpec(materialFinished.getMaterialSpec());
            //所需重量 = (计划重量 * bom对应物料用量)/100
            BigDecimal planWeightBigDecimal = new BigDecimal(String.valueOf(documentDto.getPlanWeight()));
            if (data.getLineYieldRatio() != null) {
                //产成比计算
                BigDecimal productionRatio = new BigDecimal(String.valueOf(data.getLineYieldRatio())).divide(new BigDecimal("100"));
                //排产重量 / 产成比
                BigDecimal sum = planWeightBigDecimal.divide(productionRatio,1);

                //获取占比
                String bomProportion = String.valueOf(entity.getBomDetailDosage());

                BigDecimal divide = new BigDecimal(bomProportion).divide(new BigDecimal("100"));

                BigDecimal multiply = sum.multiply(divide);

                bomDetailDto.setRequiredWeight(Double.parseDouble(String.valueOf(multiply)));
//                //产线损耗
//                BigDecimal multiply = planWeightBigDecimal.multiply(new BigDecimal(data.getLineYieldRatio()));
//                BigDecimal divide = multiply.divide(new BigDecimal(100), RoundingMode.UP);
//                BigDecimal add = divide.add(planWeightBigDecimal);
//                //根据占比进行计算
//                int bomProportion = entity.getBomDetailDosage();
//                BigDecimal multiplyProportion = add.multiply(new BigDecimal(String.valueOf(bomProportion)));
//                BigDecimal proportionWeight = multiplyProportion.divide(new BigDecimal(100), RoundingMode.UP);
//                bomDetailDto.setRequiredWeight(Double.parseDouble(String.valueOf(proportionWeight)));
            } else {
                //直接根据占比算出所需重量
                int bomProportion = entity.getBomDetailDosage();
                BigDecimal multiply = planWeightBigDecimal.multiply(new BigDecimal(String.valueOf(bomProportion)));
                BigDecimal divide = multiply.divide(new BigDecimal(100), RoundingMode.UP);
                bomDetailDto.setRequiredWeight(Double.parseDouble(String.valueOf(divide)));
            }
            //bom对应物料用量
//            int bomDetailDosage = entity.getBomDetailDosage();
//            BigDecimal subtract = planWeightBigDecimal.multiply(new BigDecimal(String.valueOf(bomDetailDosage)));
//            BigDecimal divide = subtract.divide(new BigDecimal(100), RoundingMode.UP);
//            bomDetailDto.setRequiredWeight(Double.parseDouble(String.valueOf(divide)));
            //库存重量
            Double stockWeight = storageFegin.getStockWeight(entity.getMaterialCode());
            if (stockWeight == 0) {
                throw new GlobalException("该物料无库存量，不能进行此操作!");
            } else {
                bomDetailDto.setInventoryWeight(stockWeight);
            }
            Double requiredWeight = bomDetailDto.getRequiredWeight();
//            //如果所需重量大于库存重量
//            if (requiredWeight.compareTo(stockWeight) > 0) {
//                BigDecimal subtract1 = new BigDecimal(String.valueOf(stockWeight)).multiply(new BigDecimal(100));
//                BigDecimal divide1 = subtract1.divide(new BigDecimal(data.getLineYieldRatio()), RoundingMode.UP);
//                throw new GlobalException("当前库存无法满足生产量，建议计划重量为" + divide1 + "kg");
//            }
            bomDetailDtoList.add(bomDetailDto);
        }
        documentDto.setBomDetailList(bomDetailDtoList);
        return documentDto;
    }

    /**
     * 查询bom返回仓库数据及所需用量
     *
     * @param materialCode
     * @param planWeight
     * @return
     */
    @Override
    public List<BomDetailDto> queryBom(String materialCode, double planWeight, Long bomId, Long lineId) {

        //BOM查询出来的物料列表
        AjaxResult halfData = feignService.listDetailInventory(bomId);
        List<MaterialBomHalfDetailDto> bomDetailList = JSON.parseArray(JSON.toJSONString(halfData.get("data")), MaterialBomHalfDetailDto.class);
        if (bomDetailList == null) {
            throw new GlobalException("没有查询到该物料下所属的bom明细物料数据");
        }
        List<BomDetailDto> bomDetailDtoList = new ArrayList<>();
        for (MaterialBomHalfDetailDto entity : bomDetailList) {
            BomDetailDto bomDetailDto = new BomDetailDto();
            MaterialFinished materialFinished = materialFinishedMapper.selectOne(new QueryWrapper<MaterialFinished>().lambda().eq(MaterialFinished::getMaterialCode, entity.getMaterialCode()));
            bomDetailDto.setMaterialName(materialFinished.getMaterialName());
            bomDetailDto.setMaterialCode(materialFinished.getMaterialCode());
            bomDetailDto.setMaterialSpec(materialFinished.getMaterialSpec());
            //所需重量 = (计划重量 * bom对应物料用量)/100 + 计划重量
            //所需重量 = 排产重量+产线损耗=排产重量/产成比
            BigDecimal planWeightBigDecimal = new BigDecimal(String.valueOf(planWeight));
            //获取该线别下对应的标准工时
            AjaxResult ajaxResult = schedulingPlanFeignService.hoursOnById(lineId, materialCode);
            SchedulingHoursDto data = JSON.parseObject(JSON.toJSONString(ajaxResult.get("data")), SchedulingHoursDto.class);
            if (data.getLineYieldRatio() != null) {
                //产成比计算
                BigDecimal productionRatio = new BigDecimal(String.valueOf(data.getLineYieldRatio())).divide(new BigDecimal("100"));
                //排产重量 / 产成比
                BigDecimal sum = planWeightBigDecimal.divide(productionRatio,1);

                //获取占比
                String bomProportion = entity.getBomProportion();

                BigDecimal divide = new BigDecimal(bomProportion).divide(new BigDecimal("100"));

                BigDecimal multiply = sum.multiply(divide);

                bomDetailDto.setRequiredWeight(Double.parseDouble(String.valueOf(multiply)));
            } else {
               throw new GlobalException("请先配置标准工时");
            }
            //库存重量
            Double stockWeight = storageFegin.getStockWeight(entity.getMaterialCode());

                bomDetailDto.setInventoryWeight(stockWeight);

            // Double requiredWeight = bomDetailDto.getRequiredWeight();
            // //如果所需重量大于库存重量
            // if (requiredWeight.compareTo(stockWeight) > 0) {
            //     BigDecimal subtract1 = new BigDecimal(String.valueOf(stockWeight)).multiply(new BigDecimal(100));
            //     BigDecimal divide1 = subtract1.divide(new BigDecimal(data.getLineYieldRatio()), RoundingMode.UP);
            //     throw new GlobalException("当前库存无法满足生产量，建议计划重量为" + divide1 + "kg");
            // }
            bomDetailDtoList.add(bomDetailDto);
        }
        return bomDetailDtoList;
    }

    /**
     * 新增时获取预计完工时间和预计工时
     *
     * @return
     */
    @Override
    public DegreasDocumentDto getTimeAndWorkHours(GetTimeAndWorkHoursVo getTimeAndWorkHoursVo) {
        DegreasDocumentDto documentDto = new DegreasDocumentDto();
        //获取线别id
        String lineCode = getTimeAndWorkHoursVo.getLineCode();
        Long lineId = feignService.getLineId(lineCode);
        //计算计划工时
        String materialCode = getTimeAndWorkHoursVo.getMaterialCode();
        AjaxResult ajaxResult = schedulingPlanFeignService.hoursOnById(lineId, materialCode);
        if (ajaxResult == null) {
            throw new GlobalException("该线别上有没有标准工时");
        }
        SchedulingHoursDto data = JSON.parseObject(JSON.toJSONString(ajaxResult.get("data")), SchedulingHoursDto.class);

        //标准工时（转化为秒）
        int workingHours = data.getWorkingHours();
        //单位
        int hoursUnit = data.getHoursUnit();
        //单位为KG/S
        if (hoursUnit == 2) {
            //计划重量/标准工时/360
            BigDecimal bigDecimalPlanWeight = new BigDecimal(String.valueOf(getTimeAndWorkHoursVo.getPlanWeight()));
            BigDecimal bigDecimalWorkingHours = new BigDecimal(String.valueOf(workingHours));
            BigDecimal divide = bigDecimalWorkingHours.divide(new BigDecimal("60"), RoundingMode.UP);
            BigDecimal divide1 = bigDecimalPlanWeight.divide(divide, RoundingMode.UP);
            BigDecimal divideResult = divide1.divide(new BigDecimal("60"), RoundingMode.UP);
            //预计工时
            documentDto.setResultTime(divideResult.toString());
            //预计完工时间
            SchedulingTake schedulingTake = new SchedulingTake();
            schedulingTake.setLineId(lineId);
            long expStartTime = getTimeAndWorkHoursVo.getEstimatedTime().getTime();
            double expWhen = Double.parseDouble(divideResult.toString());
            Date date = schedulingPlanFeignService.finishTime(lineId, expStartTime, expWhen);
            documentDto.setFinishWorkTime(date);
        } else {
            throw new GlobalException("该物料对应的排程计划工时单位不匹配");
        }
        return documentDto;
    }

    /**
     * 根据关联单号查询脱脂制令单信息
     *
     * @param feedOrderNumber
     * @return
     */
    @Override
    public DegreasDocument selectDegreasDocumentInfo(String feedOrderNumber) {
        return degreasDocumentMapper.selectOne(new QueryWrapper<DegreasDocument>().lambda().eq(DegreasDocument::getDegreasOrderNumber, feedOrderNumber));
    }


    /**
     * 获取生产中脱脂制令单列表(巡检单据查询调用)
     *
     * @param degreasDocumentVo
     * @return
     */
    @Override
    public List<DegreasDocumentDto> getOutDegresDocument(DegreasDocumentVo degreasDocumentVo) {

        return degreasDocumentMapper.getOutDegresDocument(degreasDocumentVo);
    }

    /**
     * 脱脂制令单pda产出列表
     *
     * @param pdaVo
     * @return
     */
    @Override
    public List<PdaDto> pdaList(PdaVo pdaVo) {

        return degreasDocumentMapper.getPdaList(pdaVo);
    }


    /**
     * 水刺及脱脂制令单合并列表
     *
     * @param spunlaceAndDegreasVo
     * @return
     */
    @Override
    public List<SpunlaceAndDegreasDto> getSpunlaceAndDegreasList(SpunlaceAndDegreasVo spunlaceAndDegreasVo) {
        List<SpunlaceAndDegreasDto> spunlaceAndDegreasDtoList = new ArrayList<>();
        //获取水刺制令单列表
        SpunlaceOrderVo spunlaceOrderVo = new SpunlaceOrderVo();
        spunlaceOrderVo.setMaterialCode(spunlaceAndDegreasVo.getMaterialCode());
        spunlaceOrderVo.setMaterialName(spunlaceAndDegreasVo.getMaterialName());
        spunlaceOrderVo.setSpunlaceOrderNumber(spunlaceAndDegreasVo.getOrderNum());
//        List<SpunlaceOrderDto> list = spunlaceOrderService.getList(spunlaceOrderVo);
//        for (SpunlaceOrderDto entity : list) {
//            SpunlaceAndDegreasDto spunlaceAndDegreasDto = new SpunlaceAndDegreasDto();
//            spunlaceAndDegreasDto.setMakingOrderNo(entity.getSpunlaceOrderNumber())
//                    .setId(entity.getId())
//                    .setMaterialCode(entity.getMaterialCode())
//                    .setMaterialCategory(Integer.parseInt(entity.getCategory()))
//                    .setMaterialName(entity.getMaterialName())
//                    .setMaterialSpec(entity.getMaterialSpec());
//            spunlaceAndDegreasDtoList.add(spunlaceAndDegreasDto);
//        }
//
//
//        //获取脱脂制令单列表
//        DegreasDocumentVo degreasDocumentVo = new DegreasDocumentVo();
//        degreasDocumentVo.setDegreasOrderNumber(spunlaceAndDegreasVo.getOrderNum());
//        degreasDocumentVo.setMaterialCode(spunlaceAndDegreasVo.getMaterialCode());
//        degreasDocumentVo.setMaterialName(spunlaceAndDegreasVo.getMaterialName());
//        List<DegreasDocumentDto> degreasDocumentList = getList(degreasDocumentVo);
//        for (DegreasDocumentDto degreasDocumentDto : degreasDocumentList) {
//            SpunlaceAndDegreasDto spunlaceAndDegreasDto = new SpunlaceAndDegreasDto();
//            spunlaceAndDegreasDto.setMakingOrderNo(degreasDocumentDto.getDegreasOrderNumber())
//                    .setId(degreasDocumentDto.getId())
//                    .setMaterialCode(degreasDocumentDto.getMaterialCode())
//                    .setMaterialCategory(degreasDocumentDto.getCategory())
//                    .setMaterialName(degreasDocumentDto.getMaterialName())
//                    .setMaterialSpec(degreasDocumentDto.getMaterialSpec());
//            spunlaceAndDegreasDtoList.add(spunlaceAndDegreasDto);
//        }
        List<SpunlaceAndDegreasDto> spunlaceAndDegreasList = degreasDocumentMapper.getSpunlaceAndDegreasList(spunlaceOrderVo);
        return spunlaceAndDegreasList;
    }
}
